package cn.com.elite;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.mail.internet.InternetAddress;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import cn.com.elite.PropertiesUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

class RunException extends Exception {
    /**
     * RunException
     */
    private static final long serialVersionUID = 1L;

    public RunException(String msg) {
        super(msg);
    }
}

public class SendBatchMail {
    private static final Log log = LogFactory.getLog(SendBatchMail.class);

    public static List goSendMail(String host, int port, String sendAdderss, String username, String password, List<Map<String, Object>> sendList) {
        // 输出要发送调用信息
        long tstartTime, tendTime, startTime, endTime, estartTime, eendTime;
        tstartTime = System.currentTimeMillis();
        // log.debug("开始批量发送邮件,配置参数信息:Start time:" + tstartTime + "-host:" + host + "-port:" + port + "-sendAdderss:" + sendAdderss + "-username:" + username + "-password:" + password);

        // 定义发送结果集
        List resultList = sendList;
        Map<String, Object> resultMap = new HashMap<String, Object>();

        // 连接邮件服务器的参数配置
        Properties properties = new Properties();
        properties.put("mail.transport.protocol", "smtp");
        properties.put("mail.smtp.auth", "true");
        properties.put("mail.smtp.host", host);
        properties.put("mail.smtp.port", port);

        // 设置系统对附件名处理方式
        System.setProperty("mail.mime.splitlongparameters", "false");

        // 创建Session对象
        Session session = Session.getInstance(properties);

        // 设置调试信息在控制台打印出来
        boolean debugBool = false;
        try {
            PropertiesUtil getProperties = new PropertiesUtil();
            debugBool = Boolean.parseBoolean(getProperties.readValue("SendBatchMail.setDebug"));
        } catch (Exception e) {
            log.error("ErrorMessage", e);
        }
        session.setDebug(debugBool);

        Transport transport = null;
        try {

            startTime = System.currentTimeMillis();

            try {
                // 根据session对象获取邮件传输对象Transport
                transport = session.getTransport();

                // 设置发件人的账户名和密码
                transport.connect(username, password);
                endTime = System.currentTimeMillis();
            } catch (Exception e) {
                throw new RunException("SendMail获取邮件传输对象Transport异常!本批次邮件发送全部失败!");
            }

            log.debug("获取邮件传输对象Transport,并建立连接Start time:" + startTime + "; End time:" + endTime + "; Run Time:" + (endTime - startTime) + "(ms)");

            Map<String, Object> receviceMap = new HashMap<String, Object>();
            String rec_guid = null;
            String receviceAddress = null;
            String ccUser = null;
            String bccUser = null;
            String subject = null;
            String content = null;
            String emlFilePath = null;

            String batch_id = null;
            String contenttype = null;
            String pipe = null;
            String relativepath = null;
            String trialcount = null;
            String trialcountlimit = null;

            List attachmentList = new ArrayList();

            // 初始化邮件推送结果
            boolean sendResult = false;
            boolean attachResult = false;

            log.debug("开始循环推送邮件,总任务数量:" + sendList.size());
            for (int i = 0; i < sendList.size(); i++) {

                sendResult = false;
                attachResult = false;

                try {
                    startTime = System.currentTimeMillis();
                    // 创建邮件的实例对象
                    MimeMessage message = new MimeMessage(session);
                    message.setFrom(new InternetAddress(sendAdderss));

                    receviceMap = sendList.get(i);
                    resultMap = receviceMap;

                    try {
                        rec_guid = GetMapV(receviceMap, "rec_guid");
                        receviceAddress = GetMapV(receviceMap, "receviceAddress");
                        ccUser = GetMapV(receviceMap, "ccUser");
                        bccUser = GetMapV(receviceMap, "bccUser");
                        subject = GetMapV(receviceMap, "subject");
                        content = GetMapV(receviceMap, "content");
                        emlFilePath = GetMapV(receviceMap, "emlFilePath");
                        attachmentList = (List<?>) receviceMap.get("attachmentList");

                        batch_id = GetMapV(receviceMap, "batch_id");
                        contenttype = GetMapV(receviceMap, "contenttype");
                        pipe = GetMapV(receviceMap, "pipe");
                        relativepath = GetMapV(receviceMap, "relativepath");
                        trialcount = GetMapV(receviceMap, "trialcount");
                        trialcountlimit = GetMapV(receviceMap, "trialcountlimit");

                    } catch (Exception e) {
                        throw new RunException("SendMail获取邮件信息异常,请检查List Map信息:" + receviceMap.toString());
                    }

                    log.debug("Rec_Guid[" + rec_guid + "]-SendMail开始推送邮件(" + i + ")信息" + "-receviceAddress:" + receviceAddress + "-subject:" + subject + "-content:" + content + "-emlFilePath:" + emlFilePath + "-attachmentList:" + attachmentList);

                    // message.setRecipients(RecipientType.TO, new InternetAddress[] { new InternetAddress(receviceAddress) });
                    // 设置多个收件地址
                    if (null != receviceAddress && !receviceAddress.isEmpty()) {
                        @SuppressWarnings("static-access") InternetAddress[] internetAddressCC = new InternetAddress().parse(receviceAddress);
                        message.setRecipients(RecipientType.TO, internetAddressCC);
                    }

                    // 设置多个抄送地址
                    if (null != ccUser && !ccUser.isEmpty()) {
                        @SuppressWarnings("static-access") InternetAddress[] internetAddressCC = new InternetAddress().parse(ccUser);
                        message.setRecipients(RecipientType.CC, internetAddressCC);
                    }

                    // 设置多个密送地址
                    if (null != bccUser && !bccUser.isEmpty()) {
                        @SuppressWarnings("static-access") InternetAddress[] internetAddressBCC = new InternetAddress().parse(bccUser);
                        message.setRecipients(RecipientType.BCC, internetAddressBCC);
                    }

                    message.setSubject(subject, "UTF-8");
                    MimeMultipart msgMultipart = new MimeMultipart("mixed");
                    MimeBodyPart mbpContent = new MimeBodyPart();

                    // 判断处理邮件格式类型
                    if ("html".equals(contenttype)) {
                        mbpContent.setContent(content, "text/html;charset=utf-8");
                    } else {
                        mbpContent.setText(content);
                    }
                    msgMultipart.addBodyPart(mbpContent);

                    // 处理邮件附件List
                    if (attachmentList != null && attachmentList.size() > 0) {
                        for (int j = 0; j < attachmentList.size(); ++j) {
                            MimeBodyPart attachment = new MimeBodyPart();
                            DataHandler dh = new DataHandler(new FileDataSource((String) attachmentList.get(j)));
                            attachment.setDataHandler(dh);
                            attachment.setFileName(MimeUtility.encodeWord(dh.getName()));
                            msgMultipart.addBodyPart(attachment);
                        }
                    }

                    message.setContent(msgMultipart);

                    attachResult = writeEml(session, message, emlFilePath, rec_guid);

                    // 发送邮件
                    estartTime = System.currentTimeMillis();
                    transport.sendMessage(message, message.getAllRecipients());

                    eendTime = System.currentTimeMillis();

                    log.debug("Rec_Guid[" + rec_guid + "]-SendMail开始传送邮件-Start time:" + estartTime + "; End time:" + eendTime + "; Run Time:" + (eendTime - estartTime) + "(ms)");

                    sendResult = true;

                } catch (Exception e) {
                    log.warn("Rec_Guid[" + rec_guid + "]-SendMail当前推送邮件Exception:", e);

                } finally {

                    resultMap.put("sendResult", sendResult);
                    resultMap.put("attachResult", attachResult);

                    resultList.set(i, resultMap);

                    endTime = System.currentTimeMillis();

                    log.debug("Rec_Guid[" + rec_guid + "]-SendMail发送邮件结束,推送Start time:" + startTime + "; End time:" + endTime + "; Run Time:" + (endTime - startTime) + "(ms)");
                }

            }

            transport.close();
            log.debug("全部任务推送End,关闭连接对象Transport完成!");

        } catch (Exception e) {
            log.error("批量发送异常！", e);

        } finally {
            if (null != transport) {
                try {
                    transport.close();
                    log.debug("成功关闭会话");
                } catch (Exception e) {
                    transport = null;
                    log.warn("关闭会话警告(忽略)");
                }
            }
        }

        tendTime = System.currentTimeMillis();
        log.debug("批量发送邮件结束 End time:" + tendTime + "; Run Time:" + (tendTime - tstartTime) + "(ms)");
        return resultList;

    }

    public static boolean writeEml(Session session, MimeMessage message, String emlFilePath, String rec_guid) {

        long tstartTime, tendTime, startTime, endTime;

        tstartTime = System.currentTimeMillis();
        log.debug("Rec_Guid[" + rec_guid + "]-File写入本地文件参数 Start time:" + tstartTime + "-emlFilePath:" + emlFilePath + "-message:" + message);

        // 将文件内容写入本地服务器
        int i = 0;
        File dirAll = new File(emlFilePath);

        do {
            startTime = System.currentTimeMillis();
            FileOutputStream fos = null;
            log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]开始将文件内容写入本地服务器:" + "-emlFilePath:" + emlFilePath + "-message:" + message);
            try {
                // 文件夹路径是否存在不存在则创建
                File dir = new File(dirAll.getParent());
                if (!dir.exists()) {
                    log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]创建EML所需路径:" + dirAll.getParent());
                    dir.mkdirs();
                }

                // 检查目标文件是否存在，不存在则创建
                if (!dirAll.exists()) {
                    log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]创建写入EML文件:" + dirAll.getName());
                    dirAll.createNewFile();
                }
                // 向目标文件中写入内容
                fos = new FileOutputStream(dirAll);
                try {
                    message.writeTo(fos);
                } catch (MessagingException e) {
                    log.error("Rec_Guid[" + rec_guid + "]-File[" + i + "]写入EML文件失败...", e);
                }
                log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]写入EML文件完成...");

            } catch (Exception e) {
                log.error("Rec_Guid[" + rec_guid + "]-File[" + i + "]写入EML文件失败：", e);
                e.printStackTrace();
            } finally {
                if (null != fos) {
                    try {
                        fos.close();
                    } catch (Exception e) {
                        log.error("Rec_Guid[" + rec_guid + "]-File[" + i + "]关闭文件流失败：", e);
                    }
                }

                endTime = System.currentTimeMillis();

                log.debug("Rec_Guid[" + rec_guid + "]-File[" + i + "]写入文件结束 Start time:" + startTime + "; End time:" + endTime + "; Run Time:" + (endTime - startTime) + "(ms)");

                i++;

            }
        } while (!dirAll.exists() && i < 3);

        tendTime = System.currentTimeMillis();
        log.debug("Rec_Guid[" + rec_guid + "]-File写入本地文件结束 End time:" + tendTime + "; Run Time:" + (tendTime - tstartTime) + "(ms)");

        return dirAll.exists();

    }

    // 解析Mapn值(此方法增加需要解析的key不存在保护)
    public static String GetMapV(Map inMap, String getKey) {
        String Rev_Value = null;
        try {
            if (inMap.containsKey(getKey)) {
                Rev_Value = String.valueOf(inMap.get(getKey));
            }
        } catch (Exception e) {

            Rev_Value = "";
        } finally {
            if (Rev_Value == null || Rev_Value.equals("null") || Rev_Value.length() <= 0) {
                Rev_Value = "";
            }
        }
        return Rev_Value;
    }

}